package cn.iocoder.yudao.module.system.service.warehouse;

import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.module.gold.convert.warehouse.GoldMaterialWarehouseConvert;
import cn.iocoder.yudao.module.system.controller.admin.warehouse.vo.GoldMaterialWarehousePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.warehouse.vo.GoldMaterialWarehouseSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.warehouse.GoldMaterialWarehouseDO;
import cn.iocoder.yudao.module.system.dal.dataobject.warehouse.GoldMaterialWarehouseUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.warehouse.GoldMaterialWarehouseMapper;
import cn.iocoder.yudao.module.system.dal.mysql.warehouse.GoldMaterialWarehouseUserMapper;
import cn.iocoder.yudao.module.system.service.warehouse.GoldMaterialWarehouseService;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_FOUND;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;

@Service
@Validated
public class GoldMaterialWarehouseServiceImpl implements GoldMaterialWarehouseService {

    @Resource
    private GoldMaterialWarehouseMapper mapper;
    
    @Resource
    private GoldMaterialWarehouseUserMapper warehouseUserMapper;

    @Override
    @Transactional
    public Long create(GoldMaterialWarehouseSaveReqVO createReqVO) {
        GoldMaterialWarehouseDO entity = GoldMaterialWarehouseConvert.INSTANCE.convert(createReqVO);
        LoginUser loginUser = getLoginUser();
        
        // 权限控制：根据仓库类型和当前用户权限判断是否可以创建
        validateCreatePermission(loginUser, createReqVO.getType());

        // 业务约束：团队仓唯一性校验（被创建人只能拥有一个团队仓）
        if (createReqVO.getType() != null && createReqVO.getType() == 2) {
            Long targetUserId = createReqVO.getUserId();
            if (targetUserId == null) {
                throw ServiceExceptionUtil.invalidParamException("团队仓必须指定用户ID");
            }
            Long exist = mapper.selectCount(
                    new LambdaQueryWrapperX<GoldMaterialWarehouseDO>()
                            .eq(GoldMaterialWarehouseDO::getType, 2)
                            .eq(GoldMaterialWarehouseDO::getUserId, targetUserId)
                            .eq(GoldMaterialWarehouseDO::getDeleted, false)
            );
            if (exist != null && exist > 0) {
                throw ServiceExceptionUtil.invalidParamException("该用户已拥有团队仓，不能重复创建");
            }
        }
        
        // 插入仓库数据
        entity.setTenantId(loginUser.getTenantId());
        mapper.insert(entity);
        
        // 插入用户-仓库关联记录
        GoldMaterialWarehouseUserDO userDO = GoldMaterialWarehouseUserDO.builder()
                .warehouseId(entity.getId())
                .userId(createReqVO.getUserId())
                .userType(createReqVO.getType())
                .build();

        warehouseUserMapper.insert(userDO);
        
        return entity.getId();
    }
    
    /**
     * 验证创建仓库的权限
     * 规则：
     * - 公司仓(type=1)：只能由公司账号(id=1)创建
     * - 团队仓(type=2)：只能由公司账号创建
     * - 人员仓(type=3)：只能由团队账号创建
     */
    private void validateCreatePermission(LoginUser loginUser, Integer warehouseType) {
        if (loginUser == null) {
            throw ServiceExceptionUtil.invalidParamException("未登录用户无法创建仓库");
        }
        
        Long currentUserId = loginUser.getId();
        
        // 查询当前用户在中间表中的userType
        List<GoldMaterialWarehouseUserDO> userRecords = warehouseUserMapper.selectList(
            new LambdaQueryWrapperX<GoldMaterialWarehouseUserDO>()
                .eq(GoldMaterialWarehouseUserDO::getUserId, currentUserId)
                .last("LIMIT 1")
        );
        Integer userType = null;
        if (userRecords.isEmpty() ) {
            if (currentUserId!=1){
                throw ServiceExceptionUtil.invalidParamException("用户权限信息不存在，无法创建仓库");
            }else if (currentUserId==1){
                userType = 1;
            }
        }else {
            userType = userRecords.get(0).getUserType();
        }

        
        // 根据仓库类型和用户权限判断
        switch (warehouseType) {
            case 1: // 公司仓：只能由公司账号创建，且userId必须为1 金料
                //判断是否以存在公司仓，存在就拒绝创建
                if (userType != 1 || currentUserId != 1) {
                    throw ServiceExceptionUtil.invalidParamException("只有公司账号可以创建公司仓");
                }
                // 检查是否已存在公司仓
                Long existingCompanyWarehouseCount = mapper.selectCount(
                    new LambdaQueryWrapperX<GoldMaterialWarehouseDO>()
                        .eq(GoldMaterialWarehouseDO::getType, 1)
                        .eq(GoldMaterialWarehouseDO::getDeleted, false)
                );
                if (existingCompanyWarehouseCount != null && existingCompanyWarehouseCount > 0) {
                    throw ServiceExceptionUtil.invalidParamException("公司仓已存在，不能重复创建");
                }
                break;
                
            case 2: // 团队仓：只能由公司账号创建
                if (userType != 1) {
                    throw ServiceExceptionUtil.invalidParamException("只有公司账号可以创建团队仓");
                }
                //检查被创建人是否拥有团队仓

                break;
                
            case 3: // 人员仓：只能由团队账号创建
                if (userType != 2) {
                    throw ServiceExceptionUtil.invalidParamException("只有团队账号可以创建人员仓");
                }
                break;
                
            default:
                throw ServiceExceptionUtil.invalidParamException("无效的仓库类型：{}", warehouseType);
        }
    }

    @Override
    public void update(GoldMaterialWarehouseSaveReqVO updateReqVO) {
        GoldMaterialWarehouseDO db = mapper.selectById(updateReqVO.getId());
        if (db == null) {
            throw ServiceExceptionUtil.invalidParamException(NOT_FOUND.getMsg());
        }
        GoldMaterialWarehouseDO entity = GoldMaterialWarehouseConvert.INSTANCE.convert(updateReqVO);
        entity.setId(updateReqVO.getId());
        mapper.updateById(entity);
    }

    @Override
    public void delete(Long id) {
        GoldMaterialWarehouseDO db = mapper.selectById(id);
        if (db == null) {
            throw ServiceExceptionUtil.invalidParamException(NOT_FOUND.getMsg());
        }
        mapper.deleteById(id);
    }

    @Override
    public GoldMaterialWarehouseDO get(Long id) {
        return mapper.selectById(id);
    }

    @Override
    public PageResult<GoldMaterialWarehouseDO> getPage(GoldMaterialWarehousePageReqVO pageReqVO) {
        LoginUser loginUser = getLoginUser();
        
        // 使用LambdaQueryWrapper构建查询条件
        LambdaQueryWrapperX<GoldMaterialWarehouseDO> wrapper = new LambdaQueryWrapperX<GoldMaterialWarehouseDO>()
                .likeIfPresent(GoldMaterialWarehouseDO::getName, pageReqVO.getName())
                .eqIfPresent(GoldMaterialWarehouseDO::getStatus, pageReqVO.getStatus())
                .orderByDesc(GoldMaterialWarehouseDO::getId);
        
        // 根据账户类型直接判断3种类型的数据
        if (loginUser != null) {
            Long userId = loginUser.getId();
            
            // 从中间表查询当前用户的userType
            List<GoldMaterialWarehouseUserDO> userRecords = warehouseUserMapper.selectList(
                new LambdaQueryWrapperX<GoldMaterialWarehouseUserDO>()
                    .eq(GoldMaterialWarehouseUserDO::getUserId, userId)
                    .last("LIMIT 1")
            );
            
            if (!userRecords.isEmpty()) {
                Integer userType = userRecords.get(0).getUserType();

                if (userType != null) {
                    switch (userType) {
                        case 1: // 公司账号：查看所有仓库（type=1,2,3都可见）
                            // 如果指定了 types 过滤（例如 [1,2] 表示只看公司仓和团队仓）
                            if (pageReqVO.getTypes() != null && !pageReqVO.getTypes().isEmpty()) {
                                wrapper.in(GoldMaterialWarehouseDO::getType, pageReqVO.getTypes());
                            }
                            break;
                            
                        case 2: // 团队账号：查看自己创建的团队仓以及其下属的所有人员仓
                            // 首先找到该团队账号创建的团队仓（type=2）
                            List<Long> teamWarehouseIds = warehouseUserMapper.selectWarehouseIdsByUserIdAndUserType(userId, 2);
                            
                            if (teamWarehouseIds.isEmpty()) {
                                // 如果没有团队仓，查询不到任何数据
                                wrapper.eq(GoldMaterialWarehouseDO::getUserId, -1L);
                            } else {
                                // 查询这些团队仓下的人员仓
                                List<Long> allowedIds = new ArrayList<>(teamWarehouseIds);
                                for (Long teamWarehouseId : teamWarehouseIds) {
                                    List<GoldMaterialWarehouseDO> personWarehouses = mapper.selectPersonWarehousesByTeamWarehouseId(teamWarehouseId);
                                    for (GoldMaterialWarehouseDO person : personWarehouses) {
                                        allowedIds.add(person.getId());
                                    }
                                }
                                
                                // 如果指定了 types 过滤（例如 [1,2]），在 allowedIds 范围内进一步过滤
                                if (pageReqVO.getTypes() != null && !pageReqVO.getTypes().isEmpty()) {
                                    // 查询 allowedIds 范围内的仓库，然后过滤 types
                                    List<GoldMaterialWarehouseDO> allWarehouses = mapper.selectList(
                                        new LambdaQueryWrapperX<GoldMaterialWarehouseDO>()
                                            .in(GoldMaterialWarehouseDO::getId, allowedIds)
                                    );
                                    
                                    List<Long> filteredIds = allWarehouses.stream()
                                        .filter(w -> pageReqVO.getTypes().contains(w.getType()))
                                        .map(GoldMaterialWarehouseDO::getId)
                                        .collect(java.util.stream.Collectors.toList());
                                    
                                    if (filteredIds.isEmpty()) {
                                        wrapper.eq(GoldMaterialWarehouseDO::getUserId, -1L);
                                    } else {
                                        wrapper.in(GoldMaterialWarehouseDO::getId, filteredIds);
                                    }
                                } else {
                                    wrapper.in(GoldMaterialWarehouseDO::getId, allowedIds);
                                }
                            }
                            break;
                            
                        case 3: // 个人账号：只能查看自己的仓库（type=3且userId=当前用户）
                            // 只查询type=3的人员仓，且userId是当前登录用户
                            boolean contains = pageReqVO.getTypes().contains(3);
                            if (contains) {
                                wrapper.eq(GoldMaterialWarehouseDO::getType, 3)
                                        .eq(GoldMaterialWarehouseDO::getUserId, userId);
                            }else {
                                wrapper.eq(GoldMaterialWarehouseDO::getUserId, -1L);
                            }
                            break;
                    }
                }
            }else {
                wrapper.eq(GoldMaterialWarehouseDO::getUserId, -1L);
            }
        }
        
        // 如果是公司账号，可以根据types参数进一步过滤
        /*if (loginUser != null) {
            Long userId = loginUser.getId();
            List<GoldMaterialWarehouseUserDO> userRecords = warehouseUserMapper.selectList(
                new LambdaQueryWrapperX<GoldMaterialWarehouseUserDO>()
                    .eq(GoldMaterialWarehouseUserDO::getUserId, userId)
                    .last("LIMIT 1")
            );
            
            // 只有公司账号才允许在权限过滤后进行 types 过滤
            if (!userRecords.isEmpty() && userRecords.get(0).getUserType() == 1) {
                if (pageReqVO.getTypes() != null && !pageReqVO.getTypes().isEmpty()) {
                    wrapper.in(GoldMaterialWarehouseDO::getType, pageReqVO.getTypes());
                }
            }
        }*/
        
        // 添加团队仓ID查询条件
        wrapper.eqIfPresent(GoldMaterialWarehouseDO::getTeamWarehouseId, pageReqVO.getTeamWarehouseId());
        
        return mapper.selectPage(pageReqVO, wrapper);
    }


    @Override
    public List<GoldMaterialWarehouseDO> getTransferOptions(Long excludeWarehouseId, List<Integer> warehouseTypes) {
        return mapper.selectTransferOptions(excludeWarehouseId, warehouseTypes);
    }

    @Override
    public List<GoldMaterialWarehouseDO> getEnabledWarehouseSimpleList() {
        return mapper.selectEnabledWarehouseSimpleList();
    }

    @Override
    public List<GoldMaterialWarehouseDO> getPersonWarehousesByTeamWarehouseId(Long teamWarehouseId) {
        return mapper.selectPersonWarehousesByTeamWarehouseId(teamWarehouseId);
    }

    @Override
    public Long getPersonWarehouseCountByTeamWarehouseId(Long teamWarehouseId) {
        return mapper.selectPersonWarehouseCountByTeamWarehouseId(teamWarehouseId);
    }

    @Override
    public List<GoldMaterialWarehouseDO> getAllTeamWarehouses() {
        return mapper.selectAllTeamWarehouses();
    }

    @Override
    public List<GoldMaterialWarehouseDO> getWarehousesByTeamWarehouseId(Long teamWarehouseId) {
        return mapper.selectWarehousesByTeamWarehouseId(teamWarehouseId);
    }

    @Override
    public List<GoldMaterialWarehouseDO> getWarehousesByTeamWarehouseIds(Long teamWarehouseId) {
        return mapper.getWarehousesByTeamWarehouseIds(teamWarehouseId);
    }
}